home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / nethack.lha / nethack-3.1 / src / spell.c < prev    next >
C/C++ Source or Header  |  1992-12-13  |  16KB  |  627 lines

  1. /*    SCCS Id: @(#)spell.c    3.1    92/12/10
  2. /*    Copyright (c) M. Stephenson 1988              */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include "hack.h"
  6.  
  7. static schar NEARDATA delay;        /* moves left for this spell */
  8. static struct obj NEARDATA *book;    /* last/current book being xscribed */
  9.  
  10. #define spelluses(spell)    spl_book[spell-1].sp_uses
  11. #define decrnuses(spell)    spl_book[spell-1].sp_uses--
  12. #define spellev(spell)        spl_book[spell-1].sp_lev
  13. #define spellname(spell)    OBJ_NAME(objects[spl_book[spell-1].sp_id])
  14. #define spellid(spell)        spl_book[spell-1].sp_id
  15.  
  16. static void FDECL(cursed_book, (int));
  17. static void FDECL(deadbook, (struct obj *));
  18. STATIC_PTR int NDECL(learn);
  19. static int NDECL(getspell);
  20. static char FDECL(spellet, (int));
  21. static char NDECL(dospellmenu);
  22.  
  23. static void
  24. cursed_book(lev)
  25.     register int    lev;
  26. {
  27.     switch(rn2(lev)) {
  28.     case 0:
  29.         You("feel a wrenching sensation.");
  30.         tele();        /* teleport him */
  31.         break;
  32.     case 1:
  33.         You("feel threatened.");
  34.         aggravate();
  35.         break;
  36.     case 2:
  37.         make_blinded(Blinded + rn1(100,250),TRUE);
  38.         break;
  39.     case 3:
  40.         take_gold();
  41.         break;
  42.     case 4:
  43.         pline("These runes were just too much to comprehend.");
  44.         make_confused(HConfusion + rn1(7,16),FALSE);
  45.         break;
  46.     case 5:
  47.         pline("The book was coated with contact poison!");
  48.         if (uarmg) {
  49.             /* Note: at this writing, there are no corrodeable
  50.              * gloves in the game.  If no one plans on adding
  51.              * copper gauntlets, most of this could be removed. -3.
  52.              */
  53.             if (uarmg->oerodeproof || !is_corrodeable(uarmg)) {
  54.             Your("gloves seem unaffected.");
  55.             } else if (uarmg->oeroded < MAX_ERODE) {
  56.             Your("gloves corrode%s!",
  57.                  uarmg->oeroded+1 == MAX_ERODE ? " completely" :
  58.                  uarmg->oeroded ? " further" : "");
  59.             uarmg->oeroded++;
  60.             } else
  61.             Your("gloves %s completely corroded.",
  62.                  Blind ? "feel" : "look");
  63.             break;
  64.         }
  65.         if(Poison_resistance) {
  66.             losestr(rn1(1,2));
  67.             losehp(rnd(6), "contact-poisoned spellbook", KILLED_BY_AN);
  68.         } else {
  69.             losestr(rn1(4,3));
  70.             losehp(rnd(10), "contact-poisoned spellbook", KILLED_BY_AN);
  71.         }
  72.         break;
  73.     case 6:
  74.         if(Antimagic) {
  75.             shieldeff(u.ux, u.uy);
  76.             pline("The book explodes, but you are unharmed!");
  77.         } else {
  78.             pline("As you read the book, it explodes in your %s!",
  79.             body_part(FACE));
  80.             losehp (2*rnd(10)+5, "exploding rune", KILLED_BY_AN);
  81.         }
  82.         break;
  83.     default:
  84.         rndcurse();
  85.         break;
  86.     }
  87.     return;
  88. }
  89.  
  90. /* special effects for The Book of the Dead */
  91. static void
  92. deadbook(book2)
  93. struct obj *book2;
  94. {
  95.     if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
  96.     register struct obj *otmp;
  97.     register boolean arti1_primed = FALSE, arti2_primed = FALSE,
  98.              arti_cursed = FALSE;
  99.  
  100.     if(book2->cursed) {
  101.         pline("The runes appear scrambled.  You can't read them!");
  102.         return;
  103.     }
  104.  
  105.     if(!u.uhave.bell || !u.uhave.menorah) {
  106.         pline("A chill runs down your spine.");
  107.         if(!u.uhave.bell) You("hear a faint chime...");
  108.         if(!u.uhave.menorah) pline("Vlad's doppelganger is amused.");
  109.         return;
  110.     }
  111.  
  112.     for(otmp = invent; otmp; otmp = otmp->nobj) {
  113.         if(otmp->otyp == CANDELABRUM_OF_INVOCATION &&
  114.            otmp->spe == 7 && otmp->lamplit) {
  115.         if(!otmp->cursed) arti1_primed = TRUE;
  116.         else arti_cursed = TRUE;
  117.         }
  118.         if(otmp->otyp == BELL_OF_OPENING &&
  119.            (moves - otmp->age) < 5L) { /* you rang it recently */
  120.         if(!otmp->cursed) arti2_primed = TRUE;
  121.         else arti_cursed = TRUE;
  122.         }
  123.     }
  124.  
  125.     if(arti_cursed) {
  126.         pline("The invocation fails!");
  127.         pline("At least one of your artifacts is cursed...");
  128.     } else if(arti1_primed && arti2_primed) {
  129.         mkinvokearea();
  130.         u.uevent.invoked = 1;
  131.     } else {    /* at least one artifact not prepared properly */
  132.         You("have a feeling that something is amiss...");
  133.         goto raise_dead;
  134.     }
  135.     return;
  136.     }
  137.  
  138.     /* when not an invocation situation */
  139.     if(book2->cursed)
  140. raise_dead:
  141.     {
  142.     register struct monst *mtmp;
  143.     coord mm;
  144.  
  145.     You("raised the dead!");
  146.     mm.x = u.ux;
  147.     mm.y = u.uy;
  148.     mkundead(&mm);
  149.     if(!rn2(4))
  150.         if(mtmp = makemon(&mons[PM_MASTER_LICH],u.ux,u.uy)) {
  151.         mtmp->mpeaceful = 0;
  152.         set_malign(mtmp);
  153.         }
  154.     } else if(book2->blessed) {
  155.     register struct monst *mtmp, *mtmp2;
  156.  
  157.     for(mtmp = fmon; mtmp; mtmp = mtmp2) {
  158.         mtmp2 = mtmp->nmon;        /* tamedog() changes chain */
  159.         if(is_undead(mtmp->data) && cansee(mtmp->mx, mtmp->my)) {
  160.         mtmp->mpeaceful = TRUE;
  161.         if(sgn(mtmp->data->maligntyp) == sgn(u.ualign.type)
  162.            && distu(mtmp->mx, mtmp->my) < 4)
  163.             if (mtmp->mtame)
  164.             mtmp->mtame++;
  165.             else
  166.             (void) tamedog(mtmp, (struct obj *)0);
  167.         else mtmp->mflee = TRUE;
  168.         }
  169.     }
  170.     } else {
  171.     switch(rn2(3)) {
  172.     case 0: 
  173.         Your("ancestors are annoyed with you!"); 
  174.         break;
  175.     case 1: 
  176.         pline("The headstones in the cemetery begin to move!");
  177.         break;
  178.     default:
  179.         pline("Oh my!  Your name appears in the book!");
  180.     }
  181.     }
  182.     return;
  183. }
  184.  
  185. STATIC_PTR
  186. int
  187. learn()
  188. {
  189.     register int    i;
  190.     register unsigned booktype;
  191.  
  192.     if (delay) {    /* not if (delay++), so at end delay == 0 */
  193.         delay++;
  194.         return(1); /* still busy */
  195.     }
  196.     exercise(A_WIS, TRUE);        /* you're studying. */
  197.     booktype = book->otyp;
  198.     if(booktype == SPE_BOOK_OF_THE_DEAD) {
  199.         deadbook(book);
  200.         return(0);
  201.     }
  202.  
  203.     for (i = 0; i < MAXSPELL; i++)  {
  204.         if (spl_book[i].sp_id == booktype)  {
  205.             if (book->spestudied >= rn1(1,8-spl_book[i].sp_lev)) {
  206.                 pline("This spellbook is too faint to be read anymore.");
  207.                 book->otyp = booktype = SPE_BLANK_PAPER;
  208.                 makeknown((int)booktype);
  209.             }
  210.             else if (spl_book[i].sp_uses < 11-spl_book[i].sp_lev) {
  211.                 Your("knowledge of that spell is keener.");
  212.                 spl_book[i].sp_uses += rn1(1,9-spl_book[i].sp_lev);
  213.                 book->spestudied++;
  214.                 exercise(A_WIS, TRUE);    /* extra study */
  215.             } else
  216.                 You("know that spell quite well already.");
  217.             break;
  218.         } else if (spl_book[i].sp_id == NO_SPELL)  {
  219.             spl_book[i].sp_id = booktype;
  220.             spl_book[i].sp_lev = objects[booktype].oc_level;
  221.             /* spells have 1 .. 9-level uses. */
  222.             /* ie 1 or 2 uses w/ most potent */
  223.             spl_book[i].sp_uses = rn1(1,9-spl_book[i].sp_lev);
  224.             book->spestudied++;
  225.             You("add the spell to your repertoire.");
  226.             makeknown((int)booktype);
  227.             break;
  228.         }
  229.     }
  230.     if (i == MAXSPELL) impossible("Too many spells memorized!");
  231.  
  232.     if (book->cursed) {    /* maybe a demon cursed it */
  233.         cursed_book(objects[booktype].oc_level);
  234.     }
  235.         check_unpaid(book);
  236.     book = 0;
  237.     return(0);
  238. }
  239.  
  240. int
  241. study_book(spellbook)
  242. register struct obj *spellbook;
  243. {
  244.     register int     booktype = spellbook->otyp;
  245.     register boolean confused = (Confusion != 0);
  246.  
  247.     if (delay && spellbook == book)
  248.         You("continue your efforts to memorize the spell.");
  249.     else {
  250.         switch(booktype)  {
  251.  
  252. /* blank spellbook */
  253.     case SPE_BLANK_PAPER:
  254.         pline("This spellbook is all blank.");
  255.         makeknown(SPE_BLANK_PAPER);
  256.         return(1);
  257. /* level 1 spells */
  258.     case SPE_HEALING:
  259.     case SPE_DETECT_MONSTERS:
  260.     case SPE_FORCE_BOLT:
  261.     case SPE_LIGHT:
  262.     case SPE_SLEEP:
  263.     case SPE_KNOCK:
  264. /* level 2 spells */
  265.     case SPE_MAGIC_MISSILE:
  266.     case SPE_CONFUSE_MONSTER:
  267.     case SPE_SLOW_MONSTER:
  268.     case SPE_CURE_BLINDNESS:
  269.     case SPE_CREATE_MONSTER:
  270.     case SPE_DETECT_FOOD:
  271.     case SPE_WIZARD_LOCK:
  272.         delay = -objects[booktype].oc_delay;
  273.         break;
  274. /* level 3 spells */
  275.     case SPE_HASTE_SELF:
  276.     case SPE_CAUSE_FEAR:
  277.     case SPE_CURE_SICKNESS:
  278.     case SPE_DETECT_UNSEEN:
  279.     case SPE_EXTRA_HEALING:
  280.     case SPE_CHARM_MONSTER:
  281.     case SPE_CLAIRVOYANCE:
  282. /* level 4 spells */
  283.     case SPE_LEVITATION:
  284.     case SPE_RESTORE_ABILITY:
  285.     case SPE_INVISIBILITY:
  286.     case SPE_FIREBALL:
  287.     case SPE_DETECT_TREASURE:
  288.         delay = -(objects[booktype].oc_level - 1) * objects[booktype].oc_delay;
  289.         break;
  290. /* level 5 spells */
  291.     case SPE_REMOVE_CURSE:
  292.     case SPE_MAGIC_MAPPING:
  293.     case SPE_CONE_OF_COLD:
  294.     case SPE_IDENTIFY:
  295.     case SPE_DIG:
  296. /* level 6 spells */
  297.     case SPE_TURN_UNDEAD:
  298.     case SPE_POLYMORPH:
  299.     case SPE_CREATE_FAMILIAR:
  300.     case SPE_TELEPORT_AWAY:
  301.         delay = -objects[booktype].oc_level * objects[booktype].oc_delay;
  302.         break;
  303. /* level 7 spells */
  304.     case SPE_CANCELLATION:
  305.     case SPE_FINGER_OF_DEATH:
  306.     case SPE_BOOK_OF_THE_DEAD:
  307.         delay = -8 * objects[booktype].oc_delay;
  308.         break;
  309. /* impossible */
  310.     default:
  311.         impossible("Unknown spellbook, %d;", booktype);
  312.         return(0);
  313.     }
  314.  
  315.         /* Books are often wiser than their readers (Rus.) */
  316.         if(!spellbook->blessed &&
  317.                 spellbook->otyp != SPE_BOOK_OF_THE_DEAD &&
  318.             (spellbook->cursed ||
  319.                 rn2(20) > (ACURR(A_INT) + 4 + (int)(u.ulevel/2)
  320.                     - 2*objects[booktype].oc_level))) {
  321.             cursed_book(objects[booktype].oc_level);
  322.             nomul(delay);            /* study time */
  323.             delay = 0;
  324.             if(!rn2(3)) {
  325.                 useup(spellbook);
  326.                 pline("The spellbook crumbles to dust!");
  327.             }
  328.             return(1);
  329.         }
  330.         else if(confused) {
  331.             if(!rn2(3) && 
  332.                 spellbook->otyp != SPE_BOOK_OF_THE_DEAD) {
  333.                 useup(spellbook);
  334.                 pline("Being confused you have difficulties in controlling your actions.");
  335.                 display_nhwindow(WIN_MESSAGE, FALSE);
  336.                 You("accidentally tear the spellbook to pieces.");
  337.             }
  338.             else
  339.                 You("find yourself reading the first line over and over again.");
  340.             nomul(delay);
  341.             delay = 0;
  342.             return(1);
  343.         }
  344.  
  345.         You("begin to %s the runes.",
  346.             spellbook->otyp == SPE_BOOK_OF_THE_DEAD ? "recite" :
  347.             "memorize");
  348.     }
  349.  
  350.     book = spellbook;
  351.     set_occupation(learn, "studying", 0);
  352.     return(1);
  353. }
  354.  
  355. static int
  356. getspell()
  357. {
  358.     register int    maxs, ilet, i;
  359.     char     lets[BUFSZ], buf[BUFSZ], qbuf[QBUFSZ];
  360.  
  361.     if (spl_book[0].sp_id == NO_SPELL)  {
  362.  
  363.         You("don't know any spells right now.");
  364.         return(0);
  365.     } else  {
  366.  
  367.         for(maxs = 1; (maxs < MAXSPELL) && (spl_book[maxs].sp_id != NO_SPELL); maxs++);
  368.         if (maxs >= MAXSPELL)  {
  369.  
  370.         impossible("Too many spells memorized.");
  371.         return(0);
  372.         }
  373.  
  374.         for(i = 0; (i < maxs) && (i < 26); buf[++i] = 0)  buf[i] = 'a' + i;
  375.         for(i = 26; (i < maxs) && (i < 52); buf[++i] = 0) buf[i] = 'A' + i - 26;
  376.  
  377.         if (maxs == 1)  Strcpy(lets, "a");
  378.         else if (maxs < 27)  Sprintf(lets, "a-%c", 'a' + maxs - 1);
  379.         else if (maxs == 27)  Sprintf(lets, "a-z A");
  380.         else Sprintf(lets, "a-z A-%c", 'A' + maxs - 27);
  381.         for(;;)  {
  382.  
  383.         Sprintf(qbuf, "Cast which spell? [%s ?]", lets);
  384.         if ((ilet = yn_function(qbuf, NULL, '\0')) == '?') {
  385.             ilet = dospellmenu();
  386.             if(!ilet)
  387.                 continue;
  388.         }
  389.         if (index(quitchars, ilet))
  390.             return(0);
  391.         else for(i = 0; buf[i] != 0; i++)
  392.             if(ilet == buf[i])  return(++i);
  393.         You("don't know that spell.");
  394.         }
  395.     }
  396. }
  397.  
  398. int
  399. docast()
  400. {
  401.     register int     spell;
  402.  
  403.     spell = getspell();
  404.     if (!spell) return(0);
  405.  
  406.     return(spelleffects(spell,FALSE));
  407. }
  408.  
  409. int
  410. spelleffects(spell,atme)
  411. register int spell;
  412. boolean atme;
  413. {
  414.     register int energy, damage;
  415.     boolean confused = (Confusion != 0);
  416.     struct obj *pseudo;
  417.  
  418.     /* note that trying to cast it decrements the # of uses,    */
  419.     /* even if the mage does not have enough food/energy to use */
  420.     /* the spell */
  421.     switch (spelluses(spell)) {
  422.         case 0:
  423.             pline ("Curdled magical energy twists through you...");
  424.             pline ("...you have overloaded and burned out this spell.");
  425.             make_confused((long)spellev(spell) * 3, FALSE);
  426.             return(0);
  427.         case 1:
  428.             Your("nerves tingle warningly.");
  429.             break;
  430.         case 2:
  431.             pline ("This spell is starting to be over-used.");
  432.             break;
  433.         default:
  434.             break;
  435.     }
  436.     decrnuses(spell);
  437.     energy = spellev(spell) * 7 / 2 - 2;    /* 1 <= energy <= 22 */
  438.     if (u.uhunger <= 100 && spell != SPE_DETECT_FOOD) {
  439.         You("are too hungry to cast that spell.");
  440.         return(0);
  441.     } else if (ACURR(A_STR) < 6)  {
  442.         You("lack the strength to cast spells.");
  443.         return(0);
  444.     } else if(check_capacity(
  445.         "Your concentration falters while carrying so much stuff.")) {
  446.         return (1);
  447.     }
  448.  
  449.     if (u.uhave.amulet) {
  450.         You("feel the amulet draining your energy away.");
  451.         energy *= rnd(3);
  452.     }
  453.     if(energy > u.uen)  {
  454.         You("don't have enough energy to cast that spell.");
  455.         return(0);
  456.     } else {
  457.         if (spell != SPE_DETECT_FOOD)
  458.             morehungry(energy * 10);
  459.         u.uen -= energy;
  460.     }
  461.     flags.botl = 1;
  462.  
  463.     if (confused ||
  464.         ((int)(ACURR(A_INT) + Luck) - 3 * spellev(spell)) < 0) {
  465.  
  466.         if (Hallucination)
  467.             pline("Far out... a light show!");
  468.         else    pline("The air around you crackles as you goof up.");
  469.         return(0);
  470.     }
  471.     exercise(A_WIS, TRUE);
  472. /*    pseudo is a temporary "false" object containing the spell stats. */
  473.     pseudo = mksobj(spellid(spell), FALSE, FALSE);
  474.     pseudo->blessed = pseudo->cursed = 0;
  475.     pseudo->quan = 20L;            /* do not let useup get it */
  476.     switch(pseudo->otyp)  {
  477.  
  478. /* These spells are all duplicates of wand effects */
  479.     case SPE_FORCE_BOLT:
  480.     case SPE_SLEEP:
  481.     case SPE_MAGIC_MISSILE:
  482.     case SPE_KNOCK:
  483.     case SPE_SLOW_MONSTER:
  484.     case SPE_WIZARD_LOCK:
  485.     case SPE_FIREBALL:
  486.     case SPE_CONE_OF_COLD:
  487.     case SPE_DIG:
  488.     case SPE_TURN_UNDEAD:
  489.     case SPE_POLYMORPH:
  490.     case SPE_TELEPORT_AWAY:
  491.     case SPE_CANCELLATION:
  492.     case SPE_FINGER_OF_DEATH:
  493.     case SPE_LIGHT:
  494.     case SPE_DETECT_UNSEEN:
  495.         if (!(objects[pseudo->otyp].oc_dir == NODIR)) {
  496.             if (atme) u.dx = u.dy = u.dz = 0;
  497.             else (void) getdir(NULL);
  498.             if(!u.dx && !u.dy && !u.dz) {
  499.                 if((damage = zapyourself(pseudo)))
  500.                 losehp(damage, 
  501.         self_pronoun("zapped %sself with a spell", "him"),
  502.                     NO_KILLER_PREFIX);
  503.             } else    weffects(pseudo);
  504.         } else weffects(pseudo);
  505.         break;
  506. /* These are all duplicates of scroll effects */
  507.     case SPE_CONFUSE_MONSTER:
  508.     case SPE_DETECT_FOOD:
  509.     case SPE_CAUSE_FEAR:
  510.     case SPE_CHARM_MONSTER:
  511.     case SPE_REMOVE_CURSE:
  512.     case SPE_MAGIC_MAPPING:
  513.     case SPE_CREATE_MONSTER:
  514.     case SPE_IDENTIFY:
  515.         (void) seffects(pseudo);
  516.         break;
  517.     case SPE_HASTE_SELF:
  518.     case SPE_DETECT_TREASURE:
  519.     case SPE_DETECT_MONSTERS:
  520.     case SPE_LEVITATION:
  521.     case SPE_RESTORE_ABILITY:
  522.     case SPE_INVISIBILITY:
  523.         (void) peffects(pseudo);
  524.         break;
  525.     case SPE_HEALING:
  526.         You("feel a bit better.");
  527.         healup(rnd(8), 0, FALSE, FALSE);
  528.         break;
  529.     case SPE_CURE_BLINDNESS:
  530.         healup(0, 0, FALSE, TRUE);
  531.         break;
  532.     case SPE_CURE_SICKNESS:
  533.         if (Sick) You("are no longer ill.");
  534.         healup(0, 0, TRUE, FALSE);
  535.         break;
  536.     case SPE_EXTRA_HEALING:
  537.         You("feel a fair bit better.");
  538.         healup(d(2,8)+2, 0, FALSE, FALSE);
  539.         break;
  540.     case SPE_CREATE_FAMILIAR:
  541.         make_familiar((struct obj *)0, u.ux, u.uy);
  542.         break;
  543.     case SPE_CLAIRVOYANCE:
  544.         do_vicinity_map();
  545.         break;
  546.     default:
  547.         impossible("Unknown spell %d attempted.", spell);
  548.         obfree(pseudo, (struct obj *)0);
  549.         return(0);
  550.     }
  551.     obfree(pseudo, (struct obj *)0);    /* now, get rid of it */
  552.     return(1);
  553. }
  554.  
  555. void
  556. losespells() {
  557.     register boolean confused = (Confusion != 0);
  558.     register int     n, nzap, i;
  559.  
  560.     book = 0;
  561.     for(n = 0;(spl_book[n].sp_id != NO_SPELL) && (n < MAXSPELL); n++);
  562.     if (!n) return;
  563.     if (n < MAXSPELL) {
  564.         nzap = rnd(n);
  565.         if (nzap < n) nzap += confused;
  566.         for (i = 0; i < nzap; i++) {
  567.             spl_book[n-i-1].sp_id = NO_SPELL;
  568.             exercise(A_WIS, FALSE);    /* ouch! */
  569.         }
  570.     } else impossible("Too many spells memorized!");
  571.     return;
  572. }
  573.  
  574. static char
  575. spellet(spl)
  576. int spl;
  577. {
  578.     return (spl < 27) ? ('a' + spl - 1) : ('A' + spl - 27);
  579. }
  580.  
  581. int
  582. dovspell()
  583. {
  584.     (void) dospellmenu();
  585.     return 0;
  586. }
  587.  
  588. static char
  589. dospellmenu()
  590. {
  591.     winid tmpwin;
  592.     register int maxs, i;
  593.     char rval;
  594.     char     buf[BUFSZ];
  595.  
  596.     if (spl_book[0].sp_id == NO_SPELL)  {
  597.  
  598.         You("don't know any spells right now.");
  599.         return 0;
  600.     }
  601.  
  602.     for(maxs = 1; (maxs < MAXSPELL) && (spl_book[maxs].sp_id != NO_SPELL); maxs++);
  603.     if (maxs >= MAXSPELL)  {
  604.  
  605.         impossible("Too many spells memorized.");
  606.         return 0;
  607.     }
  608.     tmpwin = create_nhwindow(NHW_MENU);
  609.     start_menu(tmpwin);
  610.     add_menu(tmpwin, 0, 0, "Currently known spells:");
  611.     add_menu(tmpwin, 0, 0, "");
  612.  
  613.     for(i = 1; i <= maxs; i++) {
  614.         Sprintf(buf, "%c %c %s (%d)",
  615.             spellet(i), (spelluses(i)) ? '-' : '*',
  616.             spellname(i), spellev(i));
  617.         add_menu(tmpwin, spellet(i), 0, buf);
  618.       }
  619.     end_menu(tmpwin, '\0', "\033 ", NULL);
  620.     rval = select_menu(tmpwin);
  621.     destroy_nhwindow(tmpwin);
  622.  
  623.     return rval;
  624. }
  625.  
  626. /*spell.c*/
  627.